package com.hzf.booklibrary.biz;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.LruCache;
import android.widget.ImageView;

import com.hzf.booklibrary.R;
import com.hzf.booklibrary.utils.ImageLoadUtils;

import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 图片加载类
 */
public class ImageLoader {
    private static ImageLoader mInstance;
    //图片缓存核心对象
    private LruCache<String,Bitmap> mLruCache;
    //线程池
    private ExecutorService mThreadPool;
    private static  final int DEFAULT_THREAD_COUNT=1;
    //队列调度方式
    private Type mType= Type.LIFO;
    //任务队列
    private LinkedList<Runnable> mTaskQueue;
    //后台轮询线程
    private Thread mPoolThread;
    private Handler mPoolThreadHandler;
    //UI线程的Handler
    private Handler mUIHandler;
    //信号量
    private Semaphore mSemaphorePoolThreadHandler = new Semaphore(0);
    private Semaphore mSemaphoreThreadPool;
    //是否需要裁剪 0--代表不需要裁剪，1代表需要裁剪
    public static int NEED_CROP=0x110;
    public static int NO_CROP=0x119;
    private int  isCrop=NO_CROP;
    private static final String TAG ="PdfImageLoader";
    public enum Type{
        FIFO,LIFO;
    }

    private OnLoadImageFailedListener mListener;
    private Context context;
    private ImageLoadUtils imageLoadUtils=new ImageLoadUtils();//图片加载工具类


 // /*--------------------------------------------------------------------------------------------------------*/
    public static ImageLoader getInstance(int threadCount,Type type,int isCrop,Context context){
        if(mInstance==null){
            synchronized (ImageLoader.class){
                if(mInstance==null){
                    mInstance = new ImageLoader(threadCount,type,isCrop,context);
                }
            }
        }
        return mInstance;
    }

    public void setIsCrop(int isCrop) {
        this.isCrop = isCrop;
    }

    public void setOnLoadImageFailedListener(OnLoadImageFailedListener mListener) {
        this.mListener = mListener;
    }

    private ImageLoader(int threadCount, Type type, int isCrop, Context context){
        this.isCrop=isCrop;
        this.context = context;
        init(threadCount,type);
    }
    /**
     * 初始化
     * @param threadCount
     * @param type
     */
    private void init(int threadCount, Type type) {
        //初始化后台轮询线程
        initBackThread();
        //获取最大内存--初始化LruCache
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheMemory = maxMemory/8;
        mLruCache = new LruCache<String, Bitmap>(cacheMemory){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight();
            }
        };
        //创建线程池--初始化线程池
        mThreadPool = Executors.newFixedThreadPool(threadCount);
        mTaskQueue = new LinkedList<Runnable>();
        mType=type;
        mSemaphoreThreadPool = new Semaphore(threadCount);
    }
    /**
     * 初始化后台轮询线程
     */
    private void initBackThread() {
        //后台轮询线程
        mPoolThread = new Thread(){
            @Override
            public void run() {
                Looper.prepare();
                mPoolThreadHandler = new Handler()
                {
                    @Override
                    public void handleMessage(Message msg)
                    {
                        // 线程池去取出一个任务进行执行
                        mThreadPool.execute(getTask());
                        try
                        {
                            mSemaphoreThreadPool.acquire();
                        } catch (InterruptedException e)
                        {
                        }
                    }
                };
                //释放一个信号量
                mSemaphorePoolThreadHandler.release();
                Looper.loop();
            }
        };
        mPoolThread.start();
    }

/*--------------------------------------------------------------------------------------------------------*/


    /**
     * 根据path为imageview设置图片---通知UI线程更新UI组件
     * @param path
     * @param imageView
     * @param isFromNet
     */
    public void loadImage(String path, ImageView imageView,boolean isFromNet){
        imageView.setTag(path);
        //根据path在缓存中获取图片
        Bitmap bm = getBitmapFromLruCache(path);
        if(bm!=null){
            refreshBitmap(path,imageView,bm);
        }else {
            addTask(buildTask(path,imageView,isFromNet));//创建新任务
        }
        if(mUIHandler==null){
            mUIHandler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    //获取得到图片,为Imageview设置图片
                    ImageBeanHolder holder = (ImageBeanHolder) msg.obj;
                    Bitmap bm = holder.bitmap;
                    ImageView iv = holder.imageView;
                    String path = holder.path;
                    //部分可能获取不到图片
                    if(bm==null){
                        bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.book_txt_bg);
                        if(mListener!=null){
                            mListener.onLoadImageFailed(iv.getTag().toString(),iv);
                            return;
                        }
                    }
                    //path与getTag进行比较
                    if(iv.getTag().toString().equals(path)){
                        if(isCrop==NEED_CROP){bm = cropBitmap(bm);}
                        iv.setImageBitmap(bm);
                    }
                }
            };
        }
    }


    /**
     * 从内存中获取缓存图片
     * @param path
     * @return
     */
    private Bitmap getBitmapFromLruCache(String path) {
        return mLruCache.get(path);
    }
    /**
     * 将图片加入LruCache
     */
    protected void addBitmapToLruCache(String path,Bitmap bm){
        if(getBitmapFromLruCache(path)==null){
            if(bm!=null){
                mLruCache.put(path,bm);
            }
        }
    }

 /*--------------------------------------------------------------------------------------------------------*/
    private synchronized void addTask(Runnable runnable) {
        mTaskQueue.add(runnable);
        if(mPoolThreadHandler==null){
            try {
                mSemaphorePoolThreadHandler.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        mPoolThreadHandler.sendEmptyMessage(0x110);
    }
    /**
     * 从任务队列中取出一个方法
     * @return
     */
    private Runnable getTask() {
        if(mType==Type.FIFO){
            return mTaskQueue.removeFirst();
        }else if(mType==Type.LIFO){
            return mTaskQueue.removeLast();
        }
        return null;
    }
    /**
     * 根据传入的参数，新建一个任务
     * @param path
     * @param imageView
     * @param isFromNet
     * @return
     */
    private Runnable buildTask( final String path,final ImageView imageView, final boolean isFromNet) {
        return new Runnable() {
            @Override
            public void run() {
                Bitmap bm=null;
                if(isFromNet){//从网络中获取图片并压缩
                    bm = imageLoadUtils.downloadImgByUrl(path,imageView);
                }else {//从本地获取图片
                    bm =imageLoadUtils.loadImageFromLocal(path,imageView);
                }
                //把图片加入缓存
                addBitmapToLruCache(path,bm);
                //通知UI线程更新组件
                refreshBitmap(path,imageView,bm);
                mSemaphoreThreadPool.release();
            }
        };
    }

    /**
     * 发送通知，通知更新UI
     * @param path
     * @param imageView
     * @param bm
     */
    private void refreshBitmap(String path, ImageView imageView, Bitmap bm) {
        Message msg = new Message();
        ImageBeanHolder holder = new ImageBeanHolder();
        holder.bitmap=bm;
        holder.imageView = imageView;
        holder.path=path;
        msg.obj = holder;
        mUIHandler.sendMessage(msg);
    }
    /**
     * 裁剪图片
     * @param bitmap
     * @return
     */
    public Bitmap cropBitmap(Bitmap bitmap){
        int w = bitmap.getWidth(); // 得到图片的宽，高
        int h = bitmap.getHeight();
        int wh = w > h ? h : w;// 裁切后所取的正方形区域边长
        int retX = w > h ? (w - h) / 2 : 0;//基于原图，取正方形左上角x坐标
        int retY = w > h ? 0 : (h - w) / 2;
        return Bitmap.createBitmap(bitmap, retX, retY, wh, wh, null, false);
    }
    class ImageBeanHolder{
        Bitmap bitmap;
        ImageView imageView;
        String path;
    }

    public  interface  OnLoadImageFailedListener{
        void onLoadImageFailed(String tag,ImageView imageView);
    }

}
